package com.yonyou.cyxdms.basedata.service.service.auth;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yonyou.cyx.framework.bean.dto.framework.RestResultResponse;
import com.yonyou.cyx.framework.compent.redis.RedisClient;
import com.yonyou.cyx.framework.util.http.RestHttpUtil;
import com.yonyou.cyx.function.exception.ServiceBizException;
import com.yonyou.cyx.function.utils.common.StringUtils;
import com.yonyou.cyx.function.utils.jsonserializer.JSONUtil;
import com.yonyou.cyxdms.basedata.service.constant.BasedataCommonConstants;
import com.yonyou.cyxdms.basedata.service.entity.basedata.SystemParamPO;
import com.yonyou.cyxdms.basedata.service.repository.basedata.SystemParamMapper;
import com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * 主子系统认证
 *
 * @author renwd
 * @since 2019/11/26
 */
@Service
public class ExternalUserAuthServiceImpl implements UserAuthService {

    // 日志对象
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    SystemParamMapper systemParamMapper;

    @Autowired
    RedisClient redisClient;

    @Qualifier(value = "restTemplateNoLb")
    @Autowired
    RestTemplate restTemplateNoLb;

    /**
     * 获取登录信息
     *
     * @param appId appId
     * @param jwt jwt
     * @return com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto
     * @author renwd
     * @since 2019/11/26
     */
    @Override
    public LoginInfoDto getLoginInfoDto(String appId, String jwt) {
        String key = BasedataCommonConstants.AUTH_USERINFO_KEY + appId + ":" + jwt;
        Object auth = redisClient.get(key);
        if (auth != null) {
            LoginInfoDto infoDto = JSONUtil.jsonToObj(JSONUtil.objectToJson(auth), LoginInfoDto.class);
            if (infoDto != null) {
                return infoDto;
            }
        }
        String url = queryPathUrl(BasedataCommonConstants.AUTH, appId);
        if (StringUtils.isNullOrEmpty(url)) {
            throw new ServiceBizException("未实现的认证配置，appId:{}", appId);
        }
        // 根据具体的实现获取用户信息
        LoginInfoDto dto = getAppUserInfo(appId, jwt, url);
        redisClient.set(key, dto, BasedataCommonConstants.EXPIRE_TIME_ONE_HOUR);
        return dto;
    }

    /**
     * 根据主应用的用户信息获取自己应用的用户信息
     *
     * @param appId appId
     * @param token jwt
     * @return com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto
     * @author renwd
     * @since 2019/11/26
     */
    private LoginInfoDto getAppUserInfo(String appId, String token, String url) {
        logger.debug("token:{}", token);

        HttpHeaders header = RestHttpUtil.getHeader();
        header.set(BasedataCommonConstants.TOKEN_NAME, token);
        Map<String, Object> params = new HashMap<>();
        params.put(BasedataCommonConstants.APP_ID, appId);

        // 根据token 获取用户信息
        String response = RestHttpUtil.get(params, header, restTemplateNoLb, url, String.class);

        logger.debug("appId={},远程获取userInfo:{}", appId, response);

        RestResultResponse<LoginInfoDto> responseDto = JSONUtil.jsonToObj(response,
                new TypeReference<RestResultResponse<LoginInfoDto>>() {
                });

        // 请求异常
        if (responseDto.getResultCode() != 200) {
            throw new ServiceBizException("此jwt不合法，无法换取用户信息");
        }
        LoginInfoDto loginInfo = responseDto.getData();
        loginInfo.setUuid(appId + loginInfo.getUserId());
        return loginInfo;
    }

    /**
     * 查询url
     *
     * @param paramCode code
     * @param appId appId
     * @return java.lang.String
     * @author renwd
     * @since 2019/11/26
     */
    private String queryPathUrl(String paramCode, String appId) {
        if (StringUtils.isNullOrEmpty(appId)) {
            QueryWrapper<SystemParamPO> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SystemParamPO::getAppId, "cyx")
                    .eq(SystemParamPO::getParamCode, paramCode);
            SystemParamPO systemParamPo = systemParamMapper.selectOne(queryWrapper);
            return systemParamPo.getParamValue();
        }

        QueryWrapper<SystemParamPO> systemQueryWrapper = new QueryWrapper<>();
        systemQueryWrapper.lambda().eq(SystemParamPO::getAppId, appId)
                .eq(SystemParamPO::getParamCode, paramCode);
        SystemParamPO systemParamPo = systemParamMapper.selectOne(systemQueryWrapper);
        return systemParamPo == null ? null : systemParamPo.getParamValue();
    }
}
